package demo.db.mybatis.dao;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.cursor.Cursor;

import demo.db.mybatis.pojo.User;

public interface UserMapper {

    int deleteByPrimaryKey(Integer id);

    @Delete("delete from t_user where id=#{id}")
    int deleteById(Integer id);

    int insert(User record);

    int batchInsert(Collection<User> users);

    int insertSelective(User record);

    User selectByPrimaryKey(Integer id);

    /**
     * 对于简单语句来说，注解使代码显得更加简洁，然而 Java
     * 注解对于稍微复杂的语句就会力不从心并且会显得更加混乱。因此，如果你需要做很复杂的事情，那么最好使用 XML 来映射语句。
     * 注意这里只有一个参数，则#{}中的标识符可以任意取
     */
    @Select("SELECT * FROM t_user WHERE id = #{id}")
    User selectById(Integer id);

    List<User> selectByMap(Map<String, Object> map);

    /**
     * <h1>流式查询</h1>指的是查询成功后不是返回一个集合而是返回一个迭代器，应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。
     * <p>
     * 如果没有流式查询，我们想要从数据库取 1000
     * 万条记录而又没有足够的内存时，就不得不分页查询，而分页查询效率取决于表设计，如果设计的不好，就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。
     * <p>
     * 流式查询的过程当中，数据库连接是保持打开状态的，因此要注意的是：执行一个流式查询后，数据库访问框架就不负责关闭数据库连接了，需要应用在取完数据后自己关闭。
     * <p>
     * MyBatis 提供了一个叫 org.apache.ibatis.cursor.Cursor 的接口类用于流式查询，这个接口继承了
     * java.io.Closeable 和 java.lang.Iterable 接口，由此可知：
     * <li>1、Cursor 是可关闭的； 2、Cursor 是可遍历的。
     * <p>
     * 除此之外，Cursor 还提供了三个方法：
     * <li>1、isOpen()：用于在取数据之前判断 Cursor 对象是否是打开状态。只有当打开时 Cursor 才能取数据；
     * <li>2、isConsumed()：用于判断查询结果是否全部取完。
     * <li>3、getCurrentIndex()：返回已经获取了多少条数据
     * 
     * @return
     */
    Cursor<User> streamQuery();

    int countByMap(Map<String, Object> map);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);

    @Update("update t_user set name=#{name},status=#{status} where id=#{id}")
    int updateById(User record);

    /**
     * 通过设置@Results和@Result来配置映射，其他没有配置的字段则默认规则映射对应。
     * 
     * @param id
     * @param name
     * @return
     */
    @Select("select * from t_user where id=#{id} and name like #{name}")
    @Results({ @Result(property = "status", column = "status"), @Result(property = "updateAt", column = "updateAt") })
    public User retrieveUserByIdAndName(@Param("id") int id, @Param("name") String name);

    /**
     * useGeneratedKeys = true 返回ID
     * 
     * @param user
     */
    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
    @Insert("INSERT INTO t_user(name,status) VALUES(#{name},#{status})")
    public void addNewUser(User user);

    @Insert("INSERT INTO t_user(name,status) VALUES(#{name},#{status})")
    public int insertUser(@Param("name") String name, @Param("status") Byte status);
}